package com.itheima.admin.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.itheima.admin.mapper.AdSensitiveMapper;
import com.itheima.admin.pojo.AdSensitive;
import com.itheima.admin.service.KafkaService;
import com.itheima.common.constants.BusinessConstants;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.SensitiveWordUtil;
import com.itheima.common.util.ailiyun.AliGreenScanner;
import com.itheima.common.vo.ResultVo;
import com.itheima.wemedia.dto.WmNewsContentNodeDto;
import com.itheima.dfs.fagin.DfsFeign;
import com.itheima.wemedia.fagin.WmNewsFeign;
import com.itheima.wemedia.pojo.WmNews;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class KafkaServiceImpl implements KafkaService {
    //注入自媒体微服务远程调用feign接口
    @Autowired
    private WmNewsFeign wmNewsFeign;
    @Autowired
    private AdSensitiveMapper adSensitiveMapper;
    //注入aliyun的反文本垃圾
    @Autowired
    private AliGreenScanner aliGreenScanner;
    //注入dfs远程调用的feign接口
    @Autowired
    private DfsFeign dfsFeign;
    /**
     * 文章的自动审核业务
     * @param uuid uuid
     * @param wmNewsId 文章id
     */
    @Override
    public void WmNewsSh(String uuid, Long wmNewsId) {
        //根据文章id远程调用wemedia微服务查询数据库，获取文章对象
        ResultVo<WmNews> resultVo = wmNewsFeign.findById(wmNewsId);
        //判断是否查询成功
        if (!resultVo.isSuccess()){
            //查询失败则抛出异常
            throw new LeadNewsException("远程调用自媒体微服务查询文章失败:"+uuid+wmNewsId);
        }
        //判断状态是否为1，不为1则抛出异常
        if (BusinessConstants.WmNewsConstants.STATUS_SUBMIT!=resultVo.getData().getStatus()){
            log.info("文章状态不为1");
            throw new LeadNewsException("文章状态不为待审核状态");
        }
        //获取查询到的文章对象
        WmNews wmNews = resultVo.getData();
        //判断查询到的对象是否为空
        if (wmNews==null){
            throw new LeadNewsException("文章数据为空:"+uuid+wmNewsId);
        }
        String content = wmNews.getContent();
        List<WmNewsContentNodeDto> contentList = JSON.parseArray(content, WmNewsContentNodeDto.class);
        //从文章内容中过滤出文本内容，去掉image
        List<String> textList = contentList.stream().filter(n -> "text".equals(n.getType())).map(WmNewsContentNodeDto::getValue).collect(Collectors.toList());
        //获取文章标题添加金textList集合
        textList.add(wmNews.getTitle());
        //将textList转换为字符串
        String join = String.join(",", textList);
        //对文章进行敏感词过滤
        boolean b = filterText(wmNews,join);
        //如果文章里没有铭感词则调用阿里的反垃圾机制
        aliyun(uuid,  wmNews, join, b);
    }

    /**
     * 阿里云反垃圾机制，处理
     * @param uuid
     * @param wmNews
     * @param join
     * @param b
     */
    private void aliyun(String uuid, WmNews wmNews, String join, boolean b) {
        if (!b){
            //进入这里表示文本里没有敏感词
            try {
                if (StringUtils.isNotEmpty(join)) {
                    Map<String, String> stringStringMap = aliGreenScanner.greenTextScan(join);
                    //对返回的map集合机械能非空判断，为空则抛异常
                    if (stringStringMap==null){
                        stringStringMap.get("suggestion");
                    }
                    //判断返回的map集合数据是否为pass是则件进行图片审核
                    if ("pass".equals(stringStringMap.get("suggestion"))){
                        //获取图片的文件id
                        List<String> imageList = getImageIds(wmNews);
                        //远程调用fds微服务进行图片下载获取字节数组集合
                        ResultVo<List<byte[]>> file = dfsFeign.findFile(imageList);
                        //使用aliyun的反垃圾进行图片审核
                        List<byte[]> data = file.getData();
                        Map<String, String> imageMap = aliGreenScanner.imageScan(data);
                        //判断map是否为空，为空则抛出异常
                        if (imageMap==null){
                            imageMap.get("suggestion");
                        }
                        //判断是否为pass，为pass将状态审核通过
                        if (imageMap.get("suggestion").equals("pass")){
                            WmNews wmNews1 = new WmNews();
                            wmNews1.setId(wmNews.getId());
                            wmNews1.setStatus(BusinessConstants.WmNewsConstants.STATUS_PASS);
                            ResultVo resultVo1 = wmNewsFeign.update(wmNews1);
                            if (!resultVo1.isSuccess()){
                                log.info("阿里云自动审核异常，更改为审核通过状态失败：uuid={}，文章id={}",uuid,wmNews.getId());
                            }
                            return;
                        }
                        //进入这里为审核不通过，将状态改为审核失败，填入阿里审核失败原因
                        image(uuid, wmNews, imageMap);
                    }
                    //更改文章为审核失败原因和状态
                    image(uuid, wmNews, stringStringMap);
                }
            } catch (Exception e) {
               //当返回集合为null则会抛出异常，我们这时需要，将状态改为人工审核
                WmNews wmNews1 = new WmNews();
                wmNews1.setId(wmNews.getId());
                wmNews1.setStatus(BusinessConstants.WmNewsConstants.STATUS_MANUAL);
                ResultVo resultVo1 = wmNewsFeign.update(wmNews1);
                if (!resultVo1.isSuccess()){
                    log.info("阿里云自动审核异常，更改为人工审核失败：uuid={}，文章id={}",uuid,wmNews.getId());
                }
            }
        }
    }

    /**
     * 更改文章为审核失败原因和状态
     * @param uuid
     * @param wmNews
     * @param stringStringMap
     */
    private void image(String uuid, WmNews wmNews, Map<String, String> stringStringMap) {
        WmNews wmNews2 = new WmNews();
        wmNews2.setId(wmNews.getId());
        wmNews2.setStatus(BusinessConstants.WmNewsConstants.STATUS_FAIL);
        wmNews2.setReason(stringStringMap.get("suggestion"));
        ResultVo resultVo1 = wmNewsFeign.update(wmNews2);
        if (!resultVo1.isSuccess()) {
            log.info("阿里云自动审核异常，更改状态为审核失败异常：uuid={}，文章id={}", uuid, wmNews.getId());
        }
    }

    /**
     * 获取文件图片id,存入集合
     * @param wmNews
     * @return
     */
    private List<String> getImageIds(WmNews wmNews) {
        //创建一个list接收文件数据
        List<String> imageList = new ArrayList<>();
        //获取主图的文件id
        String images = wmNews.getImages();
        //判读images是否为空，不为空则获取图片id存入list集合
        if (StringUtils.isNotEmpty(images)){
        String[] split = images.split(",");
        imageList.addAll(Arrays.asList(split));
        }
        //获取文章内容
        String content = wmNews.getContent();
        //判断文章内容是否为空，为空返回null
        if (StringUtils.isEmpty(content)){
            return imageList;
        }
        //获取文章中的图片id
        List<WmNewsContentNodeDto> contentNodeDtoList = JSON.parseArray(content, WmNewsContentNodeDto.class);
        //对文章内容进行过滤，取出type属性为image的图片id
        imageList = contentNodeDtoList.stream().filter(n -> BusinessConstants.WmNewsConstants.CONTENT_IMAGE.equals(n.getType()))
                .map(WmNewsContentNodeDto::getValue).collect(Collectors.toList());
        //对图片进行去重
        imageList.stream().distinct().collect(Collectors.toList());
        //返回获取的集合
        return imageList;
    }

    /**
     * 敏感词过滤
     * @param wmNews 文章对象
     */
    private boolean filterText(WmNews wmNews,String join) {
        //判断文本内容字符串是否有数据，为空则直接返回true
        if (StringUtils.isEmpty(join)){
            return false;
        }
        //查询敏感词表中的所有数据
        List<AdSensitive> list = adSensitiveMapper.selectList(null);
        //判断敏感词表是否有铭感词
        if (CollectionUtils.isNotEmpty(list)) {
            //过滤掉铭感词中的空白字符串
            List<String> collect = list.stream().filter(n -> !"".equals(n.getSensitives())).map(AdSensitive::getSensitives).collect(Collectors.toList());
            //调用敏感词工具类，进行敏感词审核，初始化敏感词字典
            SensitiveWordUtil.initMap(collect);
            //检查文章内容文本
            Map<String, Integer> stringIntegerMap = SensitiveWordUtil.matchWords(join);
            return stringIntegerMap.size() > 0;
        }
        return false;
    }
}
